﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.IO;
using System.Web.Hosting;
using _4T.BLL;

namespace _4T
{
    /// <summary>
    /// Summary description for FileUploadService
    /// </summary>
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]
    // To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line. 
    // [System.Web.Script.Services.ScriptService]
    public class FileUploadService : System.Web.Services.WebService
    {

        private enum FILETYLE { Audio, Video };
        /// <summary>
        /// Upload file with size less than 1MB
        /// </summary>
        /// <param name="fileSize">Size of file by byte array</param>
        /// <param name="fileName">Name of file</param>
        /// <returns></returns>
        [WebMethod(Description = "Upload small file with size less than 1MB.")]
        public string UploadSmallFile(byte[] fileSize, string fileName)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);

                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                // instance memory stream and pass the byte array of file to its constructor
                MemoryStream ms = new MemoryStream(fileSize);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(filePath, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                string fileExtension = fileName.Substring(fileName.LastIndexOf('.') + 1);
                if (fileExtension != null && fileExtension != string.Empty && string.Compare(fileExtension, "mp4", true) != 0)
                {
                    string newFileName = fileName.Substring(0, fileName.LastIndexOf('.')) + ".mp4";
                    bool isConvertSuccess = Utils.ConvertVideoType(fileName, newFileName);
                    if (isConvertSuccess) fileName = newFileName;
                }

                ProfileService.InsertProfileForVideoUpload("mobile", "guest", "FileStorage/Store/VideoUpload/" + fileName);

                // get virtual path of file
                //string virtualPath = HostingEnvironment.SiteName + HostingEnvironment.ApplicationVirtualPath + "/FileStorage/Store/" + fileName;

                // return successfull message
                //return virtualPath;
                return "File Upload Successfull";

            }
            catch (Exception ex)
            {
                // return message if any error occur
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Upload large file with size greater than 1MB.
        /// </summary>
        /// <param name="fileName">Name of file</param>
        /// <param name="filePart">Data of pack that splitted by byte array</param>
        /// <param name="indexOfPack">The index of pack</param>
        /// <param name="isFinish">The flag to notice server that the upload pack process is finished</param>
        /// <returns></returns>
        [WebMethod(Description = "Upload large file with size greater than 1MB.")]
        public string UploadLargeFile(string fileName, byte[] filePart, int indexOfPack, bool isFinish)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);
                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                MemoryStream ms = new MemoryStream(filePart);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(HostingEnvironment.MapPath("~/FileStorage/Temp/") + fileName + "." + indexOfPack, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                if (isFinish)
                {
                    return MergeFile(FILETYLE.Video, fileName, indexOfPack + 1, "mobile", "guest");
                }
                else
                {
                    return "OK";
                }
            }
            catch (Exception ex)
            {
                string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                string[] files = Directory.GetFiles(tempFolder);
                if (files != null && files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].Contains(fileName))
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            File.Delete(packInfo.FullName);
                        }
                    }
                }
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Upload file with size less than 1MB
        /// </summary>
        /// <param name="fileSize">Size of file by byte array</param>
        /// <param name="fileName">Name of file</param>
        /// <returns></returns>
        [WebMethod(Description = "Upload small file with size less than 1MB from station.")]
        public string UploadSmallFileFromStation(string stationID, byte[] fileSize, string fileName)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);

                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                // instance memory stream and pass the byte array of file to its constructor
                MemoryStream ms = new MemoryStream(fileSize);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(filePath, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                ProfileService.InsertProfileForVideoUpload("tram", stationID, "FileStorage/Store/VideoUpload/" + fileName);

                // get virtual path of file
                //string virtualPath = HostingEnvironment.SiteName + HostingEnvironment.ApplicationVirtualPath + "/FileStorage/Store/" + fileName;

                // return successfull message
                //return virtualPath;
                return "File Upload Successfull";

            }
            catch (Exception ex)
            {
                // return message if any error occur
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Upload large file with size greater than 1MB.
        /// </summary>
        /// <param name="fileName">Name of file</param>
        /// <param name="filePart">Data of pack that splitted by byte array</param>
        /// <param name="indexOfPack">The index of pack</param>
        /// <param name="isFinish">The flag to notice server that the upload pack process is finished</param>
        /// <returns></returns>
        [WebMethod(Description = "Upload large file with size greater than 1MB from station.")]
        public string UploadLargeFileFromStation(string stationID, string fileName, byte[] filePart, int indexOfPack, bool isFinish)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);
                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                MemoryStream ms = new MemoryStream(filePart);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(HostingEnvironment.MapPath("~/FileStorage/Temp/") + fileName + "." + indexOfPack, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                if (isFinish)
                {
                    return MergeFile(FILETYLE.Video, fileName, indexOfPack + 1, "tram", stationID);
                }
                else
                {
                    return "OK";
                }
            }
            catch (Exception ex)
            {
                string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                string[] files = Directory.GetFiles(tempFolder);
                if (files != null && files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].Contains(fileName))
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            File.Delete(packInfo.FullName);
                        }
                    }
                }
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        [WebMethod(Description = "Upload small file with size less than 1MB from SwitchBoard.")]
        public string UploadSmallFileFromSwitchBoard(string SwitchBoardID, byte[] fileSize, string fileName)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/Audios/" + fileName);

                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                // instance memory stream and pass the byte array of file to its constructor
                MemoryStream ms = new MemoryStream(fileSize);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(filePath, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                ProfileService.InsertProfileForAudioUpload("tongdai", SwitchBoardID, "/FileStorage/Store/Audios/" + fileName);

                // get virtual path of file
                //string virtualPath = HostingEnvironment.SiteName + HostingEnvironment.ApplicationVirtualPath + "/FileStorage/Store/" + fileName;

                // return successfull message
                //return virtualPath;
                return "File Upload Successfull";

            }
            catch (Exception ex)
            {
                // return message if any error occur
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Upload large file with size greater than 1MB.
        /// </summary>
        /// <param name="fileName">Name of file</param>
        /// <param name="filePart">Data of pack that splitted by byte array</param>
        /// <param name="indexOfPack">The index of pack</param>
        /// <param name="isFinish">The flag to notice server that the upload pack process is finished</param>
        /// <returns></returns>
        [WebMethod(Description = "Upload large file with size greater than 1MB from SwitchBoard.")]
        public string UploadLargeFileFromSwitchBoard(string SwitchBoardID, string fileName, byte[] filePart, int indexOfPack, bool isFinish)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/Audios/" + fileName);
                if (File.Exists(filePath))
                {
                    return "File already exist on server!";
                }

                MemoryStream ms = new MemoryStream(filePart);

                // instance file stream to point the storage folder
                FileStream fs = new FileStream(HostingEnvironment.MapPath("~/FileStorage/Temp/") + fileName + "." + indexOfPack, FileMode.Create);

                // write byte array from memory stream to file stream
                ms.WriteTo(fs);

                // clean up and close file
                ms.Close();
                fs.Close();
                fs.Dispose();

                if (isFinish)
                {
                    return MergeFile(FILETYLE.Audio, fileName, indexOfPack + 1, "tongdai", SwitchBoardID);
                }
                else
                {
                    return "OK";
                }
            }
            catch (Exception ex)
            {
                string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                string[] files = Directory.GetFiles(tempFolder);
                if (files != null && files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].Contains(fileName))
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            File.Delete(packInfo.FullName);
                        }
                    }
                }
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Cancel upload process.
        /// </summary>
        /// <param name="fileName">Name of file</param>
        [WebMethod(Description = "Cancel upload process.")]
        public string CancelUploadFile(string fileName)
        {
            try
            {
                bool flag = false;
                string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                string[] files = Directory.GetFiles(tempFolder);
                if (files != null && files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].Contains(fileName))
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            File.Delete(packInfo.FullName);
                            flag = true;
                        }
                    }
                }

                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);
                FileInfo file = new FileInfo(filePath);
                if (file.Exists)
                {
                    int timeToLastWrite = DateTime.Compare(DateTime.Now.AddMinutes(-1), file.LastWriteTime);
                    if (timeToLastWrite <= 0)
                    {
                        file.Delete();
                        flag = true;
                    }
                }

                if (flag)
                {
                    return "File upload is cancelled!";
                }
                else
                {
                    return "Error occur in cancelling upload process";
                }

            }
            catch (Exception ex)
            {
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        /// <summary>
        /// Check file exist on server or not
        /// </summary>
        /// <param name="fileName">Name of file</param>
        //[WebMethod(Description = "Check file exist on server or not.")]
        //public bool CheckFileExist(string fileName)
        //{
        //    string filePath = Server.MapPath("~/FileStorage/Store/" + fileName);
        //    return File.Exists(filePath);
        //    //bool result = false;
        //    //DirectoryInfo folder = new DirectoryInfo(HostingEnvironment.MapPath("~/FileStorage/") + device + "/" + user);
        //    //if (folder.Exists)
        //    //{
        //    //    string filePath = folder.FullName + "/" + fileName;
        //    //    if (File.Exists(filePath))
        //    //    {
        //    //        result = true;
        //    //    }
        //    //}

        //    //return result;
        //}

        /// <summary>
        /// Remove file on server
        /// </summary>
        /// <param name="fileName">Name of file</param>
        //[WebMethod(Description = "Remove file on server.")]
        //public string RemoveFile(string fileName)
        //{
        //    try
        //    {
        //        string filePath = Server.MapPath("~/FileStorage/Store/" + fileName);
        //        if (File.Exists(filePath))
        //        {
        //            File.Delete(filePath);

        //            return "Delete file successfully.";
        //        }
        //        else
        //        {
        //            return "File does not exist on server!";
        //        }
        //        //bool check = CheckFileExist(fileName);
        //        //if (check)
        //        //{
        //        //    string filePath = Server.MapPath("~/FileStorage/Store/" + fileName);
        //        //    File.Delete(filePath);

        //        //    return "OK";
        //        //}
        //        //else
        //        //{
        //        //    return "File does not exist on server!";
        //        //}
        //    }
        //    catch (Exception ex)
        //    {
        //        return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
        //    }
        //}

        #region Private methods
        private string MergeFile(FILETYLE fileType, string fileName, int totalPack, string fromDevice, string proposer)
        {
            try
            {
                string filePath = Server.MapPath("~/FileStorage/Store/VideoUpload/" + fileName);
                File.Create(filePath).Close();

                using (FileStream fs = new FileStream(filePath, FileMode.Append, FileAccess.Write, FileShare.Read))
                {
                    string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                    List<string> files = GetFiles(fileName, totalPack);

                    if (files != null && files.Count > 0)
                    {
                        for (int i = 0; i < files.Count; i++)
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            FileStream partStream = new FileStream(Path.Combine(tempFolder, files[i]), FileMode.Open, FileAccess.Read, FileShare.Read);
                            BinaryReader br = new BinaryReader(partStream);
                            byte[] data = br.ReadBytes((int)packInfo.Length);
                            br.Close();
                            fs.Write(data, 0, (int)packInfo.Length);
                            partStream.Close();
                            partStream.Dispose();
                        }

                        for (int i = 0; i < files.Count; i++)
                        {
                            if (files[i].Contains(fileName))
                            {
                                FileInfo packInfo = new FileInfo(files[i]);
                                File.Delete(packInfo.FullName);
                            }
                        }
                    }

                }
                string videoUrl = string.Empty;
                if (fileType == FILETYLE.Video)
                    videoUrl = "FileStorage/Store/VideoUpload/" + fileName;
                else
                    videoUrl = "FileStorage/Store/Audios/" + fileName;
                //
                //
                //

                if (fileType == FILETYLE.Video)
                {
                    string fileExtension = fileName.Substring(fileName.LastIndexOf('.') + 1);
                    if (fileExtension != null && fileExtension != string.Empty && string.Compare(fileExtension, "mp4", true) != 0)
                    {
                        string newFileName = fileName.Substring(0, fileName.LastIndexOf('.')) + ".mp4";
                        bool isConvertSuccess = Utils.ConvertVideoType(fileName, newFileName);
                        if (isConvertSuccess) videoUrl = "FileStorage/Store/VideoUpload/" + newFileName;
                    }
                }

                if (fileType == FILETYLE.Video)
                    ProfileService.InsertProfileForVideoUpload(fromDevice, proposer, videoUrl);
                else
                    ProfileService.InsertProfileForAudioUpload(fromDevice, proposer, videoUrl);
                //string virtualPath = HostingEnvironment.SiteName + HostingEnvironment.ApplicationVirtualPath + "/FileStorage/" + device + "/" + user + "/" + fileName;

                // return successfull message
                return "File Upload Successfull";
                //return virtualPath;
                //return EncryptFilePath(virtualPath);
            }
            catch (Exception ex)
            {
                string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
                string[] files = Directory.GetFiles(tempFolder);
                if (files != null && files.Length > 0)
                {
                    for (int i = 0; i < files.Length; i++)
                    {
                        if (files[i].Contains(fileName))
                        {
                            FileInfo packInfo = new FileInfo(files[i]);
                            File.Delete(packInfo.FullName);
                        }
                    }
                }
                return string.Format("Error {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        private List<string> GetFiles(string fileName, int totalPack)
        {
            string tempFolder = HostingEnvironment.MapPath("~/FileStorage/Temp/");
            string[] allFiles = Directory.GetFiles(tempFolder);
            List<string> files = new List<string>();
            for (int i = 0; i < totalPack; i++)
            {
                string[] tmp = Directory.GetFileSystemEntries(tempFolder, fileName + "." + i);

                if (tmp != null && tmp.Length > 0)
                {
                    files.Add(tmp[0]);
                }
            }

            return files;
        }

        private ProfileBLL m_ProfileBLL;
        public ProfileBLL ProfileService
        {
            get
            {
                if (m_ProfileBLL == null)
                {
                    m_ProfileBLL = new ProfileBLL();
                }
                return m_ProfileBLL;
            }
        }
        #endregion
    }
}
